home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
mref.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
25KB
|
1,076 lines
/* mref - MINIX cross referencer Author: Andy Tanenbaum */
/* Mref is intended for producing listings and cross reference maps of
* MINIX. The default is to produce three outputs:
*
* on stdout: numbered listing of all the files given as args
* on symbol.out: list of all "global" symbols and their definition line
* on xref.out: cross reference map of all references to global symbols
*
* For this program, a global symbol is one that is defined as PUBLIC, PRIVATE,
* EXTERN, #define, or SYMBOL. The latter is provided to allow users to force
* symbols x, y, and z to "global" status but simply making up a file with
*
* SYMBOL x
* SYMBOL y
* SYMBOL z
*
* The numbering is consecutive across files, i.e., the second file begins
* where the first one left off, except that each file begins at the top of
* a new page, and the line number is rounded upward to the next page.
* The three types of output can each be suppressed, using the -l, -d, and -x
* flags, respectively. Line numbering between procedures may be optionally
* suppressed with -s, as in the MINIX book. Page length and numbering can be
* user controlled with flags.
*
* Normally output is designed for a dumb line printer, but the -t flag causes
* the output to be enhanced with macros and font control so it can be fed to
* troff (or nroff). If troff form, the symbol table is printed in three
* columns, the first page being shorter to allow for the chapter opening.
*
* Flags:
* -# Number of lines to print per page, default = 50
* -d Don't produce definition file (symbol table)
* -l Don't produce listing
* -m Multiple reference on one line only are cited once
* -p n Set initial page number to n
* -t Generate troff macro call before each page
* -s Suppress line numbering between procedures
* -x Don't produce the cross reference map
*
* Examples:
* mref -60 *.c # print 60 lines per page (default is 50)
* mref -t -p 50 *.c # first page is 50; generate .Ep and .Op macros
* mref -l -d *.h *.c # no listing or symbols, just cross ref map
*/
#include <sys/types.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#define LINE_SIZE 512
#define PHYS_PAGE 66 /* physical page length */
#define DEF_LEN 50 /* default # lines/page */
#define SYM_SIZE 13 /* symbols are truncated to this size */
#define HDR_SIZE 5 /* number of lines in the default header */
#define NSYMS 2000 /* size of the symbol table */
#define NTOKENS 100 /* maximum number of tokens per line */
#define MAX_VALUES 100 /* maximum times a name can be declared */
#define MAX_PER_LINE 9 /* number of cross refs to print per line */
#define NCOLS 3 /* number of columns for troffed symbol.out */
#define SYM_FILE "symbol.out" /* place to write the symbol table */
#define XREF_FILE "xref.out" /* place to write cross ref map */
#define TMP_FILE "xref.tmp" /* temporary xref file for gathering refs */
#define SORTED_FILE "xref.sort" /* temporary xref file for sorting */
#define DEF 1 /* this line contains #define */
#define EXT 2 /* this line contains EXTERN */
#define PRIV 3 /* this line contains PRIVATE */
#define PUB 4 /* this line contains PUBLIC */
#define SYM 5 /* this line contains SYMBOL */
int listing = 1; /* 1 = output listing; 0: don't */
int xref = 1; /* 1 = output cross ref map; 0: don't */
int definitions = 1; /* 1 = output definitions; 0: don't */
int sflag = 0; /* 1 = number all lines; 0: most */
int tflag = 0; /* 1 = troff output; 0: flat */
int mflag = 0; /* 1 = max one ref/line 0: many */
int page_len = DEF_LEN; /* # lines to print per page */
int phys_page = PHYS_PAGE; /* total page size: top hdr+text+bottom hdr */
int cur_line; /* current line number */
int cur_page = 1; /* current page number */
int ntokens; /* number of tokens in the token[] array */
int suppressing; /* don't print numbers between procedures */
int hunting; /* set when hunting for end of declaration */
int comment; /* set when scanning a comment */
int xcount; /* number of references so far to this sym */
int prev_ref; /* previous reference printed */
int stride; /* length of first symbol table page */
int stride2; /* length of second symbol table page */
char *prog_name; /* argv[0] */
char line_buf[LINE_SIZE]; /* buffer for 1 line */
char b[LINE_SIZE]; /* processed line goes here */
char *token[NTOKENS]; /* array of pointers to tokens */
/* Symbol table. If a symbol is defined multiple times, it will get as many
* entries in the symbol table as there are definitions.
*/
struct symtab {
char sym_name[SYM_SIZE + 1]; /* symbol, followed by at least one '\0' */
char sym_type; /* PUB, PRIV, EXT, SYM, or DEF */
int sym_val; /* line number on which symbol occurs */
} symtab[NSYMS];
char *ppmap[] = {"", "#define", "EXTERN ", "PRIVATE", "PUBLIC ", "SYMBOL "};
char *ppmap2[] = {"", "#def", "EXTN", "PRIV", "PUBL", "SYMB"};
char spaces[] = " ";
char *xref_text[] = {
".nf\n",
".tr _\\(ru\n",
".ta 1.25i 2iR 2.45iR 2.9iR 3.35iR 3.8iR 4.25iR 4.7iR 5.15iR 5.6iR 6.05iR\n",
(char *) 0
};
char *list_text[] = {
".po .5i\n",
".lg 0\n",
".nf\n",
".ec `\n",
".ps 10\n",
".vs 12p\n",
"`f(lb\n",
".nr T `w'0'\n",
".ta 8u*`nTu 16u*`nTu 24u*`nTu 32u*`nTu 40u*`nTu 48u*`nTu 56u*`nTu 64u*`nTu 72u*`nTu 80u*`nTu\n",
".de Op \n",
".bp ``$1\n",
".sp 0.5i\n",
".tl '``fR``s10MINIX SOURCE CODE``s0'``s11File: ``$2``s0``fP'``fB``s12``n%%``s0``fP'\n",
".sp 1\n",
"``f(lb\n",
"..\n",
".de Ep \n",
".bp ``$1\n",
".sp 0.5i\n",
".tl '``fB``s12``n%%``s0``fP``fR'``s11File: ``$2'``s0``s10MINIX SOURCE CODE``s0``fP'\n",
".sp 1\n",
"``f(lb\n",
"..\n",
(char *) 0
};
char *sym_text[] = {
".nf\n",
".tr _\\(ru\n",
".ta 1.6iR 2.0i 3.6iR 4.0i 5.6iR\n",
(char *) 0
};
FILE *sym; /* for symbol table file */
FILE *xr; /* for cross reference file */
FILE *tmp; /* for collecting cross references */
FILE *sortf; /* for sorting cross refernces */
main(argc, argv)
int argc;
char *argv[];
{
int i, j;
char *p;
prog_name = argv[0];
/* Process the command line. */
if (argc < 2) usage();
for (i = 1; i < argc; i++) {
p = argv[i];
if (*p != '-') break;
p++;
i += eat_flag(argv, i);
}
stride = page_len / 2; /* allow for chapter opening */
stride2 = page_len;
/* Create the output files. */
make_files();
/* Read all the files. Make the listing and extract the symbols. */
for (j = i; j < argc; j++) process(argv[j]);
if (xref) {
/* Read all the files again and generate the cross
* refererence data. */
cur_line = 0;
for (j = i; j < argc; j++) gen_xref(argv[j]);
/* Go get the cross reference data and print it. */
collect_xref();
}
/* Print the symbol table. */
if (definitions) print_sym();
exit(0);
}
int eat_flag(argv, i)
char *argv[]; /* argument array */
int i; /* process argv[i] */
{
char *p;
int r = 0;
p = argv[i];
p++;
if (*p >= '0' && *p <= '9') {
page_len = atoi(p); /* e.g. numb -60 file */
return(r);
}
while (1) {
/* Flag may be something like -dls. */
switch (*p) {
case 'd': definitions = 0; break;
case 'l': listing = 0; break;
case 'x': xref = 0; break;
case 'm': mflag = 1; break;
case 's': sflag = 1; break;
case 't': tflag = 1; break;
case 'p':
cur_page = atoi(argv[i + 1]);
i++;
r = 1;
break;
default: usage();
}
p++;
if (*p == 0) return(r);
}
}
make_files()
{
/* Create output files. */
int fd;
if (tflag && listing) output_macros(stdout, list_text);
if (definitions) {
if ((fd = creat(SYM_FILE, 0666)) < 0) {
fprintf(stderr, "%s: cannot create %s\n", prog_name, SYM_FILE);
exit(2);
}
close(fd);
sym = fopen(SYM_FILE, "w");
if (sym == NULL) {
fprintf(stderr,
"%s: cannot open %s for output\n", prog_name, SYM_FILE);
exit(2);
}
if (tflag) output_macros(sym, sym_text);
}
if (xref) {
if ((fd = creat(XREF_FILE, 0666)) < 0) {
fprintf(stderr,"%s: cannot create %s\n", prog_name, XREF_FILE);
exit(2);
}
close(fd);
xr = fopen(XREF_FILE, "w");